﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LightCAD.MathLib
{
    public class Transform3d
    {
        private Matrix4 matrix;
        private Quaternion quaternion = new Quaternion();
        public Vector3 Origin { get; } 
        public Vector3 Position { get; } = new Vector3();
        public Euler Euler { get; } = new Euler(0, 0, 0, Euler.RotationOrders.XYZ);
        public Vector3 Scales { get; } = new Vector3(1, 1, 1);
        public bool IsMirror
        {
            get
            {
                return Scales.ToArray().Count(v => v < 0) % 2 != 0;
            }
        }
        public Matrix4 Matrix
        {
            get
            {
                if (matrix == null)
                {
                    var orignMat = ThreadContext.GetCurrThreadContext().Matrix4Ctx._m1.MakeTranslation(-this.Origin.X, -this.Origin.Y, -this.Origin.Z);
                    this.matrix = new Matrix4().Compose(Position, quaternion, Scales).Multiply(orignMat); 
                }
                return matrix;
            }
            set
            {
                matrix = value;
                matrix.Decompose(Position, Euler, Scales);
            }
        }
        public Transform3d(Vector3 origin=null)
        {
            this.Origin = origin??new Vector3();
            this.Euler.OnChange(() => this.quaternion.SetFromEuler(this.Euler));
        }
        public bool OnlyTranslate() 
        {
            if(this.Euler.X==this.Euler.Y&& this.Euler.Y == this.Euler.Z&& this.Euler.Y == 0 
                && this.Scales.X==this.Scales.Y&&this.Scales.X==this.Scales.Z &&this.Scales.X==1)
                return true;
            return false;
        }
        public bool IsIdentity() 
        {
            if(OnlyTranslate()&& this.Position.X==this.Position.Y&&this.Position.X==this.Position.Z&&this.Position.X==0)
                return true;
            else return false;
        }
        public Transform3d Update() 
        {
            this.matrix = null;
            return this;
        }
        public Transform3d Copy(Transform3d source) 
        {
            this.Euler.Copy(source.Euler);
            this.Position.Copy(source.Position);
            this.Scales.Copy(source.Scales);
            return this;
        }
        public Transform3d Clone() 
        {
            return new Transform3d().Copy(this);
        }
    }
}
